//-------------------------------------------------------------
// Classe permettant la tesselation
//
//
// 
// voir: http://www.flipcode.com/tutorials/tut_tesselation.shtml
//-------------------------------------------------------------
#include "Tess_poly.h"

#ifndef CALLBACK	// pour le bon fonctionnement
#define CALLBACK	// de windows & unix lors de 
#endif				// fragmentations de polygones ... Voir RedBook Chap. 11

//--------------------------
// routines de callback
//--------------------------

// combineCallback( ) returns new vertex coordinates and color data if the GLU_TESS_COMBINE
// is invoked. The new vertex is created by referencing the contents of vertex_data. coords
// is the location of the new vertex. weight[4] is used to interpolate the average RGB value
// for newly created vertices. 

void CALLBACK combineCallback(GLdouble coords[3], GLdouble *vertex_data[4], GLfloat weight[4], GLdouble **dataOut )
 {
    GLdouble *vertex;
    int i;

   vertex = (GLdouble *) malloc(6 * sizeof(GLdouble));

   vertex[0] = coords[0];
   vertex[1] = coords[1];
   vertex[2] = coords[2];
   for (i = 3; i < 6; i++)
		 vertex[i] = weight[0] * vertex_data[0][i] 
                   + weight[1] * vertex_data[1][i]
                   + weight[2] * vertex_data[2][i] 
                   + weight[3] * vertex_data[3][i];
    
   *dataOut = vertex;
}


 
// Now we have to define our vertex callback function, vertexCallback( ). This function creates
// a pointer to the vertex's data (the vertex_data pointer) that is passed to it and references
// the coordinate and color data. 

void CALLBACK vertexCallback(GLvoid *vertex)
{
	GLdouble *ptr;

	ptr = (GLdouble *) vertex;
	glVertex3dv((GLdouble *) ptr);
	glColor3dv((GLdouble *) ptr + 3);
}






//----------------------------------------- INIT --------------------------------------------------
// Tess_Poly::Init() sets up everything for basic tessellation. It creates the tessellation
// objects and specifies the callback functions. GLU_TESS_BEGIN and GLU_TESS_END are pointed
// to the OpenGL functions glBegin( ) and glEnd( ), respectively. GLU_TESS_COMBINE is associated
// with a user-defined function, combineCallback( ), which will be defined later. GLU_TESS_VERTEX
// is also associated with a user-defined function, vertexCallback, which will also be defined 
// and explained later.
 
Tess_Poly::Init(GLint type_de_rendu)
{
	// Create a new tessellation object 
	tobj = gluNewTess(); 

	// Set callback functions
    if(type_de_rendu == RENDU_BASIC) gluTessCallback(tobj, GLU_TESS_VERTEX,(void (CALLBACK*)())&glVertex3dv);
	if (type_de_rendu==RENDU_COMBINE) gluTessCallback(tobj, GLU_TESS_VERTEX, (void (CALLBACK*)())&vertexCallback);
	gluTessCallback(tobj, GLU_TESS_BEGIN, (void (CALLBACK*)())&glBegin);
	gluTessCallback(tobj, GLU_TESS_END, (void (CALLBACK*)())&glEnd);
	if (type_de_rendu==RENDU_COMBINE) gluTessCallback(tobj, GLU_TESS_COMBINE, (void (CALLBACK*)())&combineCallback);

	return(1);
}


//-------------------------- Set_Winding_Rule -----------------------------------------------------
// Tess_Poly::Set_Winding_Rule( ) simply sets the winding rule to the value of winding_rule
// for the current polygon.
 
Tess_Poly::Set_Winding_Rule(GLenum winding_rule)
{
	// Set the winding rule
	gluTessProperty(tobj, GLU_TESS_WINDING_RULE, winding_rule); 
	return(1);
}


//-----------------------  Render_Contour  --------------------------------------------------------
// Tess_Poly::Render_Contour( ) renders a full contour of a polygon. obj_data refers to the array
// that contains all the vertex data for the contour. For what we need, the vertex data will include
// the vertex coordinate and color value. num_vertices is the number of vertices for the contour. 

Tess_Poly::Render_Contour(GLdouble obj_data[][6], int num_vertices)
{
	for (int x = 0; x < num_vertices; x++) //loop through the vertices
	{
		gluTessVertex(tobj, obj_data[x], obj_data[x]); //store the vertex
	}
	return(1);
}

//---------------------  Begin_Polygon ------------------
// Tess_Poly::Begin_Polygon( ) initializes a new polygon. 

Tess_Poly::Begin_Polygon(GLvoid)
{
	gluTessBeginPolygon(tobj, NULL);
	return(1);
}


//---------------------- End_Polygon --------------------
// Tess_Poly::End_Polygon( ) ends a polygon. 

Tess_Poly::End_Polygon(GLvoid)
{
	gluTessEndPolygon(tobj);
	return(1);
}


//------------------------ Begin_Contour -------------------
// Tess_Poly::Begin_Contour( ) initializes a new contour of the current polygon. 

Tess_Poly::Begin_Contour(GLvoid)
{
	gluTessBeginContour(tobj);
	return(1);
}


//------------------------ End_Contour ---------------------- 
//Tess_Poly::End_Contour( ) ends the current contour. 

Tess_Poly::End_Contour(GLvoid)
{
	gluTessEndContour(tobj);
	return(1);
}

//-------------- End ------------------------------------ 
//Tess_Poly::End( ) deletes the tessellation object. 

Tess_Poly::End(GLvoid)
{
	gluDeleteTess(tobj);
	return(1);
}

 



 
